﻿using System;
using System.Drawing;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Interop;

namespace System
{
    /// <summary>
    /// 屏幕工具类
    /// </summary>
    public static class ScreenUtility
    {
        /// <summary>
        /// 获取主屏幕大小
        /// </summary>
        /// <returns>《宽度，高度》</returns>
        public static Tuple<double, double> GetMainScreenSize()
        {
            var screenHeight = SystemParameters.PrimaryScreenHeight;
            var screenWidth = SystemParameters.PrimaryScreenWidth;

            return new Tuple<double, double>(screenWidth, screenHeight);
        }

        /// <summary>
        /// 获取主屏幕工作区大小
        /// </summary>
        /// <returns>《宽度，高度》</returns>
        public static Tuple<double, double> GetMainWorkAreaSize()
        {
            var width = SystemParameters.WorkArea.Width;
            var height = SystemParameters.WorkArea.Height;

            return new Tuple<double, double>(width, height);
        }

        /// <summary>
        /// 获取某个窗口所在的屏幕的大小
        /// </summary>
        /// <param name="dependencyObject">窗口或者窗口中的控件</param>
        /// <exception cref="ArgumentException">找不到指定的窗口</exception>
        /// <returns>屏幕大小《宽度，高度》</returns>
        public static Tuple<double, double> GetScreenSize(this DependencyObject dependencyObject)
        {
            IntPtr windowHandle;         //窗口句柄
            Screen screen;               //窗口所在的屏幕
            Tuple<double, double> size;  //窗口大小

            #region 找到窗口句柄
            {
                var window = Window.GetWindow(dependencyObject);
                if (window == null)
                {
                    throw new ArgumentException("找不到指定的窗口", nameof(dependencyObject));
                }

                windowHandle = new WindowInteropHelper(window).Handle;
            }
            #endregion

            #region 获取窗口屏幕
            screen = Screen.FromHandle(windowHandle);
            #endregion

            #region 计算窗口大小
            {
                //缩放比例
                double scaling = GetScreenZoom(windowHandle);

                var width = screen.Bounds.Width / scaling;
                var height = screen.Bounds.Height / scaling;
                size = new Tuple<double, double>(width, height);
            }
            #endregion

            return size;
        }

        /// <summary>
        /// 获取某个窗口所在的屏幕的工作区的大小
        /// </summary>
        /// <param name="dependencyObject">窗口或者窗口中的控件</param>
        /// <exception cref="ArgumentException">找不到指定的窗口</exception>
        /// <returns>工作区大小《宽度，高度》</returns>
        public static Tuple<double, double> GetWorkAreaSize(this DependencyObject dependencyObject)
        {
            IntPtr windowHandle;         //窗口句柄
            Screen screen;               //窗口所在的屏幕
            Tuple<double, double> size;  //窗口大小

            #region 找到窗口句柄
            {
                var window = Window.GetWindow(dependencyObject);
                if (window == null)
                {
                    throw new ArgumentException("找不到指定的窗口", nameof(dependencyObject));
                }

                windowHandle = new WindowInteropHelper(window).Handle;
            }
            #endregion

            #region 获取窗口屏幕
            screen = Screen.FromHandle(windowHandle);
            #endregion

            #region 计算窗口大小
            {
                //缩放比例
                double scaling = GetScreenZoom(windowHandle);

                var width = screen.WorkingArea.Width / scaling;
                var height = screen.WorkingArea.Height / scaling;
                size = new Tuple<double, double>(width, height);
            }
            #endregion

            return size;
        }

        /// <summary>
        /// 截屏
        /// </summary>
        /// <param name="dependencyObject">窗口或者窗口中的控件</param>
        /// <param name="x">左上角点的X</param>
        /// <param name="y">左上角点的Y</param>
        /// <param name="width">要截取的宽度</param>
        /// <param name="height">要截取的高度</param>
        /// <returns></returns>
        public static Image GetScreenShot(this DependencyObject dependencyObject, int x = 0, int y = 0, int width = 0, int height = 0)
        {
            IntPtr windowHandle;         //窗口句柄
            Screen screen;               //窗口所在的屏幕
            Image result;

            #region 找到窗口句柄
            {
                var window = Window.GetWindow(dependencyObject);
                if (window == null)
                {
                    throw new ArgumentException("找不到指定的窗口", nameof(dependencyObject));
                }

                windowHandle = new WindowInteropHelper(window).Handle;
            }
            #endregion

            #region 获取窗口屏幕
            screen = Screen.FromHandle(windowHandle);
            #endregion
            int tempX = x + (int)(screen.WorkingArea.X / GetScreenZoom(windowHandle));

            if (width == 0)
            {
                width = screen.Bounds.Width;
                height = screen.Bounds.Height;
            }

            #region 截屏
            result = new Bitmap(width, height);
            using (Graphics g = Graphics.FromImage(result))
            {
                g.CopyFromScreen(new System.Drawing.Point(tempX, y), new System.Drawing.Point(0, 0), screen.Bounds.Size);
            }
            #endregion

            return result;
        }

        /// <summary>
        /// 获取屏幕放大/缩放比例
        /// </summary>
        public static double GetScreenZoom(this DependencyObject dependencyObject)
        {
            double zoom = 1;
            try
            {
                var window = Window.GetWindow(dependencyObject);
                if (window == null)
                {
                    throw new ArgumentException("找不到指定的窗口", nameof(dependencyObject));
                }

                var windowHandle = new WindowInteropHelper(window).Handle;
                zoom = GetScreenZoom(windowHandle);
            }
            catch (Exception)
            {

            }
            return zoom;
        }

        /// <summary>
        /// 获取屏幕放大/缩放比例
        /// </summary>
        public static double GetScreenZoom(IntPtr intPtr)
        {
            double zoom = 1;
            try
            {
                using (Graphics currentGraphics = Graphics.FromHwnd(intPtr))
                {
                    zoom = currentGraphics.DpiX / 96;
                }
            }
            catch (Exception)
            {

            }
            return zoom;
        }
    }
}
